clc;
clear all;
close all;


%% Simulator 1
% Compute with n = 4, 8, 16, 32
% With k = 0 to n/4
% 4 methods: minimax, constant correction, var, and hyb
fprintf('SIMULATOR\n');
N = [4,8,10];

err_zr = cell(length(N), 1);
err_mn = cell(length(N), 1);
err_cc = cell(length(N), 1);
err_vr = cell(length(N), 1);
err_hb = cell(length(N), 1);

for i = 1:length(N)
    fprintf('--------------------------------------------------------------\n');
    fprintf('N = %d\n', N(i));
    
    
    n = N(i); r = N(i); lower = 0.0; upper = 0.99999999999;
    K_Max = floor(N(i)/2.0) + 1;
    K = 0:K_Max;
    
    step = 2^(-n);
    num = (round((upper-lower)/step) + 1);
    
    err_zr_k = zeros(2, length(K));
    err_mn_k = zeros(2, length(K));% 1,j - err 2,j - correction value
    err_cc_k = zeros(2, length(K));
    err_vr_k = zeros(2, length(K));
    err_hb_k = zeros(2, length(K));     
    
    for j = 1:length(K)        
        fprintf('\t k = %d\n', K(j));
        k = K(j);
        %correction constant
        cor_const = ccm_const(n, n, r, k);
        err_cc_k(2, j) = cor_const;
        %minimax constant
        [mnx_const, mnx_err] = get_mn(lower, upper, n, n, r, k);
        err_mn_k(1, j) = mnx_err;
        err_mn_k(2, j) = mnx_const;
                
        index = 0;
        for a = lower:step:upper
            tStart = tic;
            index = index + 1;
            for b = lower:step:upper
                                             
                %True answer
                ans_true = a * b;
                
                %Zero answer
                ans_zr = trunc_mult(a, b, 0.0, n, n, r, k);
                err_zr_ab = abs(ans_zr - ans_true);
                err_zr_k(1, j) = max([err_zr_ab, err_zr_k(1, j)]);
                %Minimax Constant
%                 ans_mn = trunc_mult(a, b, mnx_const, n, n, r, k);
%                 err_mn = abs(ans_mn - ans_true);
%                 err_mn_k(j) = max([err_mn, err_cc_k(j)]);
                
                %Correction Constant                
                ans_cc = trunc_mult(a, b, cor_const, n, n, r, k);              
                err_cc_ab = abs(ans_cc - ans_true);
                err_cc_k(1, j) = max([err_cc_ab, err_cc_k(1, j)]);
                
                %Variable
                [ans_vr,f_vr] = vcm(a, b, n, n, r, k);
                err_vr_ab = abs(ans_vr - ans_true);
                err_vr_k(1, j) = max([err_vr_ab, err_vr_k(1, j)]);
                err_vr_k(2, j) = max([f_vr, err_vr_k(2, j)]);
                
                %Hybrid
                [ans_hb,f_hb] = hcm(a, b, n, n, r, k, 0.5);
                err_hb_ab = abs(ans_hb - ans_true);
                err_hb_k(1, j) = max([err_hb_ab, err_hb_k(1, j)]);  
                err_hb_k(2, j) = max([f_hb, err_hb_k(2, j)]);
                            
            end
            tLoop = toc(tStart);   
            percent = double(index/num) * 100;
            tLeft = tLoop * (num - index);
            fprintf('\t\tN = %d - k = %d - Index = %d - Num = %d - Percent: %f - Time: %s - Left: %f hrs\n',n,k,index, num, percent, datestr(datenum(0,0,0,0,0,tLoop),'HH:MM:SS'),tLeft/3600.0 );
                       
        end
        
    end   
    err_zr{i} = err_zr_k;
    err_cc{i} = err_cc_k;
    err_mn{i} = err_mn_k;
    err_vr{i} = err_vr_k;
    err_hb{i} = err_hb_k;
    fprintf('\n');
end
save('data.mat', 'err_cc', 'err_mn', 'err_vr', 'err_hb');

%% PLOT
close all;
N = [4,8,10];
for i = 1:length(N)
    figure;
    ulp = 2^(-N(i));
    %err_zr_k = err_zr{i};
    err_cc_k = err_cc{i};
    err_mn_k = err_mn{i};
    err_vr_k = err_vr{i};
    err_hb_k = err_hb{i};
    ulpline = ulp * ones(size(err_zr_k, 2));
     
    %plot(0:size(err_zr_k, 2) - 1, err_zr_k(1,:), 'k-x'); hold on; 
    plot(0:size(err_mn_k, 2) - 1, err_mn_k(1,:), 'm-o'); hold on; 
    plot(0:size(err_cc_k, 2) - 1, err_cc_k(1,:), 'c-*'); hold on; 
    plot(0:size(err_vr_k, 2) - 1, err_vr_k(1,:), 'b-+'); hold on; 
    plot(0:size(err_hb_k, 2) - 1, err_hb_k(1,:), 'g-d'); hold on;
    plot(0:size(err_zr_k, 2) - 1,  ulpline, 'r-x'); 
    legend('Minimax','CCT', 'VCT', 'HCT', 'ulp');
end
